package com.base.logistics.jdl.request;

import com.base.logistics.config.JdlConfig;
import com.base.logistics.jdl.util.json.JdlGsonBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.base.logistics.jdl.bean.RequestParams;
import com.base.logistics.jdl.bean.token.TokenResult;
import com.google.gson.JsonObject;
import org.apache.commons.lang3.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import static com.base.logistics.jdl.util.sign.SignUtil.encode;
import static com.base.logistics.jdl.util.sign.SignUtil.md5;

/**
 * <pre>
 * 京东快递api接口实现
 * </pre>
 * @since 2021-02-21
 */
public class JdlApiRequestConfig implements JdlRequestConfig {

    /**
     * 错误返回
     */
    private static final String ERROR_RESPONSE = "error_response";

    private final Log log = LogFactory.get(this.getClass().getName());

    private JdlConfig config;

    @Override
    public void setConfig(JdlConfig config) throws Exception {
        this.refreshToken(config);
    }

    @Override
    public JdlConfig getConfig() {
        return this.config;
    }

    @Override
    public <T> T execute(RequestParams request, Class<T> clazz) throws Exception {
        try {
            String result = request.build(this.config).execute().body();
            if(StrUtil.isBlank(result)){
                throw new Exception("无响应内容");
            }
            if (result.contains(ERROR_RESPONSE)) {
                throw new Exception("error response");
            }
            this.resultSuccess(request,result);
            log.debug("【result】: {} \n",result);
            return JdlGsonBuilder.create().fromJson(result, clazz);
        }catch (HttpException e){
            throw new Exception("接口请求发生错误");
        }
    }

    private void refreshToken(JdlConfig config) throws Exception {
        if(config.getEnabled()) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
            dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
            String timestamp = dateFormat.format(new Date());

            String sign = md5(config.getAppSecret() + "app_key" + config.getAppKey() + "refresh_token" + config.getRefreshToken() + "timestamp" + timestamp + config.getAppSecret());

            String url = config.getUrl() +
                    "/oauth/refresh_token_ext?LOP-DN=oauth.jdwl.com&app_key=" +
                    config.getAppKey() +
                    "&refresh_token=" + config.getRefreshToken() +
                    "&timestamp=" + encode(timestamp) +
                    "&sign=" + sign;
            try {
                String result = HttpRequest.post(url).execute().body();
                if (StrUtil.isBlank(result)) {
                    throw new Exception("无响应内容");
                }
                if (result.contains(ERROR_RESPONSE)) {
                    throw new Exception("error response");
                }
                TokenResult r = TokenResult.fromJson(result);
                if (!r.isSuccess()) {
                    throw new Exception(r.getErrMsg());
                }
                config.setToken(r.getModel().getAccessToken());
                config.setPin(r.getModel().getSellerId());
                this.config = config;
            } catch (HttpException e) {
                throw new Exception("接口请求发生错误");
            }
        }
    }

    private void resultSuccess(RequestParams request, String result) throws Exception {
        JsonObject obj = JdlGsonBuilder.create().fromJson(result, JsonObject.class);
        if(!obj.has(request.getCodeField())){
            throw new Exception("状态码不存在");
        }
        Integer code = obj.get(request.getCodeField()).getAsInt();
        if(!request.getSuccessCode().equals(code)){
            throw new Exception(String.valueOf(code));
        }
    }
}
